package speed2010.andreza.vspeed.gui;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map.Entry;

import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.GroupLayout;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.LayoutStyle;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;

import prefuse.Display;
import speed2010.andreza.vspeed.integration.CommunicationManager;
import speed2010.andreza.vspeed.integration.NodeGeneric;
import speed2010.andreza.vspeed.util.SwingUtils;
import speed2010.andreza.vspeed.view.ConsolidadorInfoPrefuse;
import speed2010.andreza.vspeed.view.QueryFocusControl;
import speed2010.application.gui.VirtualNodeInfo;
import speed2010.middleware.comunicacao.Address;
import speed2010.middleware.serviceOverlay.node.NodeType;

/**
 * @author <a href="mailto:andreza.lba@gmail.com">Andreza Leite de Alencar</a>
 */
public class PanelChooseDomain extends javax.swing.JPanel {

	private static final long serialVersionUID = 1L;
	private JScrollPane jScrollPanelDomain;
	private JScrollPane jScrollPanelPeer;
	private JProgressBar jProgressBarNetwork;
	private JList jListDomains;
	private JPanel jPanelNetwork;

	private ConsolidadorInfoPrefuse consolidadorInfoPrefuse;

	private final Object mutex = new Object();
	private Object source;

	public PanelChooseDomain(Object source) {
		super();
		initGUI();
		loadDomains();
		this.source = source;
	}

	private void initGUI() {
		try {
			final GroupLayout thisLayout = new GroupLayout(this);
			setLayout(thisLayout);
			setPreferredSize(new java.awt.Dimension(800, 592));
			this.jScrollPanelPeer = new JScrollPane();
			this.jScrollPanelPeer.setBorder(BorderFactory.createTitledBorder("2 -  Select a peer to see its schema"));
			this.jScrollPanelPeer.setBackground(new java.awt.Color(255, 255, 255));
			{
				this.jPanelNetwork = new JPanel();
				this.jScrollPanelPeer.setViewportView(this.jPanelNetwork);
				this.jPanelNetwork.setBackground(new java.awt.Color(255, 255, 255));
				this.jPanelNetwork.setBorder(BorderFactory.createTitledBorder("Nework Visualization"));
				this.jPanelNetwork.setPreferredSize(new java.awt.Dimension(373, 499));
			}

			{
				this.jScrollPanelDomain = new JScrollPane();
				this.jScrollPanelDomain.setBackground(new java.awt.Color(255, 255, 255));
				this.jScrollPanelDomain.setBorder(BorderFactory
						.createTitledBorder("1 - Select an information domain to proceed with the query"));
				{
					final ListModel jList1Model = new DefaultComboBoxModel(new String[]{});
					this.jListDomains = new JList();
					this.jListDomains.setModel(jList1Model);

					this.jScrollPanelDomain.setViewportView(this.jListDomains);
					this.jListDomains.setBorder(BorderFactory.createTitledBorder(null, "Domain Filter",
							TitledBorder.LEADING, TitledBorder.DEFAULT_POSITION));
					this.jListDomains.setPreferredSize(new java.awt.Dimension(373, 540));
				}
			}
			thisLayout.setVerticalGroup(thisLayout
					.createSequentialGroup()
					.addContainerGap()
					.addGroup(
							thisLayout
									.createParallelGroup()
									.addComponent(this.jScrollPanelDomain, GroupLayout.Alignment.LEADING, 0, 527,
											Short.MAX_VALUE)
									.addComponent(this.jScrollPanelPeer, GroupLayout.Alignment.LEADING, 0, 527,
											Short.MAX_VALUE)).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
					.addComponent(getJProgressBarNetwork(), GroupLayout.PREFERRED_SIZE, 37, GroupLayout.PREFERRED_SIZE)
					.addContainerGap());
			thisLayout.setHorizontalGroup(thisLayout
					.createSequentialGroup()
					.addContainerGap()
					.addGroup(
							thisLayout
									.createParallelGroup()
									.addGroup(
											GroupLayout.Alignment.LEADING,
											thisLayout.createSequentialGroup()
													.addComponent(this.jScrollPanelDomain, 0, 385, Short.MAX_VALUE)
													.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
													.addComponent(this.jScrollPanelPeer, 0, 385, Short.MAX_VALUE))
									.addComponent(getJProgressBarNetwork(), GroupLayout.Alignment.LEADING, 0, 780,
											Short.MAX_VALUE)).addContainerGap());
		} catch (final Exception e) {
			e.printStackTrace();
		}
	}

	private void loadDomains() {
		this.jProgressBarNetwork.setIndeterminate(true);

		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					initializeTopology();
					Thread.sleep(3000);
				} catch (final InterruptedException e) {
					e.printStackTrace();
				}
				final CommunicationManager manager = CommunicationManager.getInstance();
				manager.recoveryTopologyInfo();

				final NodeGeneric genericPeer = manager.getGenericPeer();

				final Display d = PanelChooseDomain.this.consolidadorInfoPrefuse.gerarDisplay(
						genericPeer.getMapAddressReduzido_NodeInfo(), true, true);
				final QueryFocusControl queryFocusControl = new QueryFocusControl(2, this);
				d.addControlListener(queryFocusControl);

				PanelChooseDomain.this.jPanelNetwork.removeAll();
				PanelChooseDomain.this.jPanelNetwork.add(d);

				synchronized (PanelChooseDomain.this.mutex) {
					PanelChooseDomain.this.mutex.notify();
				}
			}
		}).start();

		new Thread(new Runnable() {
			@Override
			public void run() {
				synchronized (PanelChooseDomain.this.mutex) {
					try {
						PanelChooseDomain.this.mutex.wait();
						PanelChooseDomain.this.jProgressBarNetwork.setIndeterminate(false);

						final List<String> domains = new ArrayList<String>();
						domains.add("All Domains");

						final NodeGeneric nodeGeneric = CommunicationManager.getInstance().getGenericPeer();
						final Hashtable<String, VirtualNodeInfo> mapNodes = nodeGeneric
								.getMapAddressReduzido_NodeInfo();
						for (final Entry<String, VirtualNodeInfo> entry : mapNodes.entrySet()) {
							final VirtualNodeInfo nodeInfo = entry.getValue();
							if (nodeInfo.getNodeType().equals(NodeType.PEERSEMANTICO)) {
								domains.add(nodeInfo.getDominio());
							}
						}

						PanelChooseDomain.this.jScrollPanelDomain.setViewportView(getListDomains(domains
								.toArray(new String[]{})));

					} catch (final InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}

	/**
	 * Prepare the results information and map result information
	 */
	private void initializeTopology() {
		final Runnable rPrepareTopology = new Runnable() {
			@Override
			public void run() {
				PanelChooseDomain.this.consolidadorInfoPrefuse = new ConsolidadorInfoPrefuse(null);
				final CommunicationManager manager = CommunicationManager.getInstance();
				manager.sendPrepareTopolyMessage();
			}
		};

		final Thread tPrepareTopology = new Thread(rPrepareTopology);
		tPrepareTopology.start();
	}

	private JList getListDomains(final String[] domainsElements) {
		this.jListDomains = new JList(domainsElements);
		this.jListDomains.setPreferredSize(new java.awt.Dimension(366, 379));
		this.jListDomains.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		this.jListDomains.addMouseListener(new java.awt.event.MouseAdapter() {
			@Override
			public void mousePressed(final java.awt.event.MouseEvent e) {
				updateDomainGraph();
			}
		});

		if (domainsElements.length > 0) {
			this.jListDomains.setSelectedIndex(0);
		}
		updateDomainGraph();

		return this.jListDomains;
	}

	private JProgressBar getJProgressBarNetwork() {
		if (this.jProgressBarNetwork == null) {
			this.jProgressBarNetwork = new JProgressBar();
		}
		return this.jProgressBarNetwork;
	}

	/**
	 * 
	 */
	private void updateDomainGraph() {
		final String domain = (String) this.jListDomains.getSelectedValue();

		final CommunicationManager manager = CommunicationManager.getInstance();
		final NodeGeneric genericPeer = manager.getGenericPeer();

		final Hashtable<String, VirtualNodeInfo> mapNodeInfo = genericPeer.getMapAddressReduzido_NodeInfo();
		Display d = null;

		if (this.jListDomains.getSelectedIndex() == 0) {
			d = this.consolidadorInfoPrefuse.gerarDisplay(mapNodeInfo, true, true);
		} else if (this.jListDomains.getSelectedIndex() > 0) {
			d = this.consolidadorInfoPrefuse.updateDisplay(mapNodeInfo, domain, true, true);
		}
		final QueryFocusControl queryFocusControl = new QueryFocusControl(2, this);
		d.addControlListener(queryFocusControl);

		this.jPanelNetwork.removeAll();
		this.jPanelNetwork.add(d);
	}

	public void notifySelectedNode(final Integer id, final String type) {
		final CommunicationManager manager = CommunicationManager.getInstance();
		final Hashtable<String, VirtualNodeInfo> mapNodes = manager.getGenericPeer().getMapAddressReduzido_NodeInfo();
		Address selectNode = null;
		for (final Entry<String, VirtualNodeInfo> entry : mapNodes.entrySet()) {
			if (entry.getValue().getAddress().getPorta() == id) {
				selectNode = entry.getValue().getAddress();
				break;
			}
		}

		if (selectNode != null) {
			final String msg = "Use ontology from node: " + selectNode.getIP() + " ?";
			boolean confirmation = SwingUtils.confirmacao(new JFrame(), msg);

			if (confirmation) {
				manager.recoveryPDOntology(selectNode);
				manager.setUsingAnyOntology(true);
				SwingUtils.infoMessage(new JFrame(), "Ontology loaded with sucess. Please specify your query.", "Ontology load.");
				if (source == GUIConstants.GUI_INSTANCE.jMenuItemVisualQuery) {
					GUIConstants.GUI_INSTANCE.changePanel(new PanelVisualQuery());
				} else if (source == GUIConstants.GUI_INSTANCE.jMenuItemSparQL) {
					GUIConstants.GUI_INSTANCE.changePanel(new PanelSparQL());
				}
			}
		}
	}
}
